home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / mit2mo~1.zoo / src / parser.y < prev    next >
Encoding:
Lex Description  |  1995-08-14  |  8.5 KB  |  383 lines

  1. %{
  2. #include "global.h"
  3.  
  4. #define CMB_UMINUS    ('-' | 0x80)
  5. #define CMB_UNEG    ('!' | 0x80)
  6.  
  7. extern unsigned long tmp_labels[10][2], tmp_label_cnt;
  8. extern char *msprintf P_((const char *, ...));
  9. extern struct numstr combine P_((struct numstr, struct numstr, int));
  10. %}
  11.  
  12. %union {
  13.   long num;
  14.   char *str;
  15.   struct numstr numstr;
  16. }
  17.  
  18. %token NL
  19. %token <str> OP OP_MREG ID STRING REG TMPLABEL TMPLABELfb
  20. %token <str> D_COMM D_LCOMM D_ELIST D_IDLIST D_NONE D_OPTINT D_ORG
  21. %token <str> D_SLIST D_UNS
  22. %token <num> NUMBER
  23.  
  24. %type <str> operand reglist regrange expr sym_expr size_field
  25. %type <str> expr_list id_list string_list
  26. %type <num> op
  27. %type <numstr> num_val
  28.  
  29. %left '+' '-'
  30. %left '&' '^' '!' '|'
  31. %left '*' '/' '%' '>' '<'
  32. %left UMINUS
  33.  
  34. %%
  35.  
  36. prog: linelist;
  37.  
  38. linelist: /* nothing */
  39.         | linelist line {fputc('\n', yyout);}
  40.         ;
  41.  
  42. line: label directives NL
  43.     | label instr NL
  44.     | label NL
  45.     | macro NL
  46.     ;
  47.  
  48. label: /* nothing */
  49.      | ID ':' {
  50.      fprintf(yyout, "%s:", $1);
  51.      if (strlen($1) > 6) fputc('\n', yyout);
  52.      free($1);
  53.        }
  54.      | TMPLABEL {
  55.        int i = $1[0] - '0';
  56.      if (tmp_labels[i][1] == 0)
  57.        tmp_labels[i][0] = ++tmp_label_cnt;
  58.      else
  59.        tmp_labels[i][0] = tmp_labels[i][1];
  60.      tmp_labels[i][1] = 0;
  61.      fprintf(yyout, "LT%lu:", tmp_labels[i][0]);
  62.        }
  63.      ;
  64.  
  65. directives: directive
  66.       | directives ';' {fputc('\n', yyout);} directive
  67.       ;
  68.  
  69. directive: D_COMM ID ',' num_val {
  70.          fprintf(yyout, "\t%s\t%s, %ld", $1, $2, $4.num);
  71.          free($1); free($2); free($4.str);
  72.        }
  73.      | D_LCOMM ID ',' num_val {
  74.          fprintf(yyout, "%s:%s\t%s\t%ld", $2,
  75.            (strlen($2) <= 6 ? "" : "\n"), $1, $4.num
  76.          );
  77.          free($1); free($2); free($4.str);
  78.        }
  79.      | D_ELIST expr_list {
  80.          fprintf(yyout, "\t%s\t%s", $1, $2); free($1); free($2);
  81.        }
  82.      | D_IDLIST id_list {
  83.          fprintf(yyout, "\t%s\t%s", $1, $2); free($1); free($2);
  84.        }
  85.      | D_NONE {
  86.          fprintf(yyout, "\t%s", $1); free($1);
  87.        }
  88.      | D_OPTINT {
  89.          fprintf(yyout, "\t%s", $1); free($1);
  90.        }
  91.      | D_OPTINT num_val {
  92.          fprintf(yyout, "\t%s", $1); free($1); free($2.str);
  93.        }
  94.      | D_ORG expr {
  95.          fprintf(yyout, "\t%s\t%s", $1, $2); free($1); free($2);
  96.        }
  97.      | D_SLIST string_list {
  98.          fprintf(yyout, "\t%s\t%s", $1, $2); free($1); free($2);
  99.        }
  100.      | D_UNS {yyerror("warning: unsupported assembler directive %s", $1);}
  101.      ;
  102.  
  103. instr: OP {fprintf(yyout, "\t%s", $1);}
  104.      | OP operand {
  105.      fprintf(yyout, "\t%s\t%s", $1, $2); free($1); free($2);
  106.        }
  107.      | OP operand ',' operand {
  108.      fprintf(yyout, "\t%s\t%s, %s", $1, $2, $4);
  109.      free($1); free($2); free($4);
  110.        }
  111.      | OP_MREG reglist ',' operand {
  112.      fprintf(yyout, "\t%s\t%s, %s", $1, $2, $4);
  113.      free($1); free($2); free($4);
  114.        }
  115.      | OP_MREG operand ',' reglist {
  116.      fprintf(yyout, "\t%s\t%s, %s", $1, $2, $4);
  117.      free($1); free($2); free($4);
  118.        }
  119.      ;
  120.  
  121. operand: '#' expr {$$ = msprintf("#%s", $2); free($2);}
  122.        | REG {$$ = $1;}
  123.        | REG '@' {$$ = msprintf("(%s)", $1); free($1);}
  124.        | REG '@' '+' {$$ = msprintf("(%s)+", $1); free($1);}
  125.        | REG '@' '-' {$$ = msprintf("-(%s)", $1); free($1);}
  126.        | REG '@' '(' expr ')' {
  127.        $$ = msprintf("%s(%s)", $4, $1);
  128.        free($1); free($4);
  129.      }
  130.        | REG '@' '(' expr ',' REG size_field ')' {
  131.        $$ = msprintf("%s(%s,%s%s)", $4, $1, $6, $7);
  132.        free($1); free($4); free($6); free($7);
  133.      }
  134.        | expr {$$ = $1;}
  135.        ;
  136.  
  137. macro: ID '=' expr {
  138.      fprintf(yyout, "%s\t=\t%s", $1, $3);
  139.      free($1); free($3);
  140.        }
  141.      ;
  142.  
  143. size_field: /* nothing */  {$$[0] = '\0';}
  144.       | ':' ID {$$ = msprintf(".%s", $2); free($2);}
  145.       ;
  146.  
  147. reglist: regrange {$$ = $1;}
  148.        | REG '/' REG {$$ = msprintf("%s/%s", $1, $3); free($1); free($3);}
  149.        | REG '/' regrange {
  150.         $$ = msprintf("%s/%s", $1, $3);
  151.         free($1); free($3);
  152.       }
  153.        | reglist '/' REG {
  154.         $$ = msprintf("%s/%s", $1, $3);
  155.         free($1); free($3);
  156.       }
  157.        | reglist '/' regrange {
  158.         $$ = msprintf("%s/%s", $1, $3);
  159.         free($1); free($3);
  160.       }
  161.        ;
  162.  
  163. regrange: REG '-' REG {
  164.         $$ = msprintf("%s-%s", $1, $3);
  165.         free($1); free($3);
  166.       }
  167.     ;
  168.  
  169. expr: num_val {$$ = msprintf("%ld", $1); free($1.str);}
  170.     | sym_expr {$$ = $1;}
  171.     ;
  172.  
  173. sym_expr: ID {$$ = $1;}
  174.     | TMPLABELfb {
  175.       int i = $1[0] - '0';
  176.       unsigned long l;
  177.         if ($1[1] == 'f') {
  178.           if (tmp_labels[i][1] == 0)
  179.         tmp_labels[i][1] = ++tmp_label_cnt;
  180.           l = tmp_labels[i][1];
  181.         } else {
  182.           l = tmp_labels[i][0];
  183.           if (l == 0)
  184.         yyerror("Unresolved temporary label %db", i);
  185.         }
  186.         $$ = msprintf("LT%lu", l); free($1);
  187.       }
  188.     | sym_expr op sym_expr {
  189.         $$ = msprintf("%s%c%s", $1, (char)$2, $3);
  190.         free($1); free($3);
  191.       }
  192.     | num_val op sym_expr {
  193.         $$ = msprintf("%s%c%s", $1.str, (char)$2, $3);
  194.         free($1.str); free($3);
  195.       }
  196.     | sym_expr op num_val {
  197.         $$ = msprintf("%s%c%s", $1, (char)$2, $3.str);
  198.         free($1); free($3.str);
  199.       }
  200.     ;
  201.  
  202. op: '+' {$$ = '+';}
  203.   | '-' {$$ = '-';}
  204.   | '&' {$$ = '&';}
  205.   | '^' {$$ = '^';}
  206.   | '|' {$$ = '|';}
  207.   | '*' {$$ = '&';}
  208.   | '/' {$$ = '/';}
  209.   | '%' {$$ = '%';}
  210.   | '<' {$$ = '<';}
  211.   | '>' {$$ = '>';}
  212.   ;
  213.  
  214. num_val: NUMBER {$$.num = $1; $$.str = msprintf("%ld", $1);}
  215.        | num_val op num_val {$$ = combine($1, $3, (int)$2);}
  216.        | '-' num_val %prec UMINUS {$$ = combine($2, $2, CMB_UMINUS);}
  217.        | '!' num_val %prec UMINUS {$$ = combine($2, $2, CMB_UNEG);}
  218.        | '(' num_val ')' {$$ = $2;}
  219.        ;
  220.  
  221. expr_list: expr {$$ = $1;}
  222.      | expr_list ',' expr {
  223.          $$ = msprintf("%s, %s", $1, $3);
  224.          free($1); free($3);
  225.        }
  226.      ;
  227.  
  228. id_list: ID {$$ = $1;}
  229.        | id_list ',' ID {
  230.        $$ = msprintf("%s, %s", $1, $3);
  231.        free($1); free($3);
  232.      }
  233.        ;
  234.  
  235. string_list: STRING {$$ = $1;}
  236.        | string_list ',' STRING {
  237.            $$ = msprintf("%s, %s", $1, $3);
  238.            free($1); free($3);
  239.          }
  240.        ;
  241.  
  242. %%
  243.  
  244. #include <stdarg.h>
  245. #include <string.h>
  246. #include <time.h>
  247. #include <unistd.h>
  248. #include "global.h"
  249. #include "patchlev.h"
  250.  
  251. #ifdef __MINT__
  252. long _stksize = 65536L;
  253. #endif
  254.  
  255. unsigned long tmp_labels[10][2];
  256. unsigned long tmp_label_cnt;
  257.  
  258. #ifdef __STDC__
  259. char *msprintf(const char *fmt, ...)
  260. #else
  261. char *msprintf(fmt)
  262.      const char *fmt;
  263. #endif
  264. {
  265.   va_list ap;
  266.   static char buf[256];
  267.  
  268.   va_start(ap, fmt);
  269.   vsprintf(buf, fmt, ap);
  270.   va_end(ap);
  271.   return strdup(buf);
  272. }
  273.  
  274. struct numstr combine(n1, n2, op)
  275.      struct numstr n1, n2;
  276.      int op;
  277. {
  278.   struct numstr n0;
  279.  
  280.   if (op & 0x80) {
  281.     n0.str = msprintf("%c%s", (op ^ 0x80), n1.str);
  282.     free(n1.str);
  283.   } else {
  284.     n0.str = msprintf("%s%c%s", n1.str, op, n2.str);
  285.     free(n1.str); free(n2.str);
  286.   }
  287.  
  288.   switch (op) {
  289.     case '+': n0.num = n1.num + n2.num; break;
  290.     case '-': n0.num = n1.num - n2.num; break;
  291.     case '&': n0.num = n1.num & n2.num; break;
  292.     case '^': n0.num = n1.num ^ n2.num; break;
  293.     case CMB_UNEG: n0.num = !n1.num; break;
  294.     case '|': n0.num = n1.num | n2.num; break;
  295.     case '*': n0.num = n1.num & n2.num; break;
  296.     case '/': n0.num = n1.num / n2.num; break;
  297.     case '%': n0.num = n1.num % n2.num; break;
  298.     case '<': n0.num = n1.num << n2.num; break;
  299.     case '>': n0.num = n1.num >> n2.num; break;
  300.     case CMB_UMINUS: n0.num = -n1.num; break;
  301.   }
  302.  
  303.   return n0;
  304. }
  305.  
  306. main(ac, av)
  307.      int ac;
  308.      char *av[];
  309. {
  310.   char *s, buf[40], outfnam[40];
  311.   int i;
  312.   time_t t;
  313.   struct tm *T;
  314.  
  315. #if YYDEBUG != 0
  316.   yydebug = 1;
  317. #endif
  318.   if ((ac != 2) && (ac != 4)) {
  319.     fprintf(stderr, "usage: %s [-o filename] filename\n", av[0]);
  320.     exit(1);
  321.   }
  322.   if (!(yyin = fopen(av[ac - 1], "r"))) {
  323.     fprintf(stderr, "%s: cannot open input file %s\n", av[0], av[ac - 1]);
  324.     exit(1);
  325.   }
  326.   if (ac == 4) {
  327.     strcpy(outfnam, av[2]);
  328.   } else {
  329.     strcpy(outfnam, av[ac - 1]);
  330.     s = strrchr(outfnam, '.');
  331.     if (!s)
  332.       strcat(outfnam, ".s");
  333.     else
  334.       strcpy(s + 1, "s");
  335.   }
  336.   if (!(yyout = fopen(outfnam, "w"))) {
  337.     fprintf(stderr, "%s: cannot open output file %s\n", av[0], outfnam);
  338.     exit(1);
  339.   }
  340.   time(&t);
  341.   T = localtime(&t);
  342.   strftime(buf, 40, "%b %d %Y %H:%M:%S", T);
  343.   fprintf(yyout, "; Generated by mit2mot v%d.%d.%d on %s\n\n",
  344.     M2M_VERSION, M2M_RELEASE, M2M_PATCHLEVEL, buf);
  345.   init_hash();
  346.   if (yyparse() != 0) {
  347.     clear_hash();
  348.     fclose(yyin);
  349.     fclose(yyout);
  350.     unlink(outfnam);
  351.     exit(1);
  352.   }
  353.   for (i = 0; i < 10; i++)
  354.     if (tmp_labels[i][1] != 0) {
  355.       yyerror("Unresolved temporary label %df", i);
  356.       fprintf(yyout, "LT%lu:\n", tmp_labels[i][1]);
  357.     }
  358.   clear_hash();
  359.   fclose(yyin);
  360.   fclose(yyout);
  361.   return 0;
  362. }
  363.  
  364. #ifdef __STDC__
  365. void yyerror(const char *s, ...)
  366. #else
  367. void yyerror(s)
  368.      const char *s;
  369. #endif
  370. {
  371.   va_list ap;
  372.  
  373.   fprintf(stderr, "At line %lu:  ", line_num);
  374.   va_start(ap, s);
  375.   vfprintf(stderr, s, ap);
  376.   va_end(ap);
  377.   fputc('\n', stderr);
  378. }
  379.  
  380. #ifndef yywrap
  381. yywrap() {return 1;}
  382. #endif
  383.